package au.edu.adelaide.adept_sdk_java;


public class AdeptSDKJava {
	
	static{
		if(AdeptSDKJavaLoader.isNativeLoaded()){
			//AdeptSDKJavaLoader.loadNative();
		}
		
	}
	
	private int lastEnum = -1;
	
	
	public HIF createHIFHandle(){
		return new HIF();
	}
	
	public DVC createDVCHandle(){
		return new DVC();
	}
	
	public boolean jDmgrOpen(HIF hif, String boardName) throws HIFDisposedException{
		if(hif.disposed){throw new HIFDisposedException();}
		return DmgrOpen(hif, boardName);
	}
	
	public boolean jDmgrClose(HIF hif) throws HIFDisposedException{
		if(hif.disposed){throw new HIFDisposedException();}
		return DmgrClose(hif);
	}
	
	public boolean jDmgrEnumDevices(int[] pcdvc){
		boolean result = DmgrEnumDevices(pcdvc);
		if(result){
			lastEnum = pcdvc[0];
			return result;
		}
		lastEnum = -1;
		return false;
		
	}
	
	public boolean jDmgrFreeDvcEnum(){
		boolean result = DmgrFreeDvcEnum();
		if(result){
			lastEnum = -1;
		}
		return false;
		
	}
	
	
	public boolean jDmgrGetDvc(int idvc, DVC dvc){
		if(dvc == null){
			return false; // should be exception but oh well
		}
		if(idvc < 0 || idvc > lastEnum){
			return false; // should be an exception but oh well
		}
		boolean result = DmgrGetDvc(idvc, dvc);
		dvc.loaded = result;
		return result;
	}
	
	public boolean jDeppEnable(HIF hif) throws HIFDisposedException{
		if(hif.disposed){throw new HIFDisposedException();}
		if(DeppEnable(hif)){
			hif.deppEnabled = true;
			return true;
		}else{
			return false;
		}
	}
	
	public boolean jDeppDisable(HIF hif) throws HIFDisposedException, DeppNotEnabledException{
		if(hif.disposed){throw new HIFDisposedException();}
		if(!hif.deppEnabled){throw new DeppNotEnabledException();}
		return DeppDisable(hif);
	}
	
	public boolean jDeppPutReg(HIF hif, byte address, byte data, boolean overlap)  throws HIFDisposedException, DeppNotEnabledException{
		if(hif.disposed){throw new HIFDisposedException();}
		if(!hif.deppEnabled){throw new DeppNotEnabledException();}
		return DeppPutReg(hif, address, data, overlap);
	}
	
	public boolean jDeppGetReg(HIF hif, byte address, byte[] data, boolean overlap)  throws HIFDisposedException, DeppNotEnabledException{
		if(hif.disposed){throw new HIFDisposedException();}
		if(!hif.deppEnabled){throw new DeppNotEnabledException();}
		return DeppGetReg(hif, address, data, overlap);
	}
	
	public boolean jDeppPutRegRepeat(HIF hif, byte address, byte[] data, int size, boolean overlap) throws HIFDisposedException, DeppNotEnabledException{
		if(hif.disposed){throw new HIFDisposedException();}
		if(!hif.deppEnabled){throw new DeppNotEnabledException();}
		if(data.length < size){throw new ArrayIndexOutOfBoundsException();}
		return DeppPutRegRepeat(hif, address, data, size, overlap);
	}
	
	public boolean jDeppGetRegRepeat(HIF hif, byte address, byte[] data, int n, boolean overlap) throws HIFDisposedException, DeppNotEnabledException{
		if(hif.disposed){throw new HIFDisposedException();}
		if(!hif.deppEnabled){throw new DeppNotEnabledException();}
		if(data.length < n){throw new ArrayIndexOutOfBoundsException();}
		return DeppGetRegRepeat(hif, address, data, n, overlap);
	}
	
	private native long allocateHIF();
	
	private native void deallocateHIF(long handlePointer);
	
	private native long allocateDVC();
	
	private native void deallocateDVC(long handlePointer);
	
	private native String getDVCszName(DVC dvc);
	
	private native String getDVCszConn(DVC dvc);
	
	
	
	private native boolean DmgrOpen(HIF hif, String boardName);
	
	private native boolean DmgrClose(HIF hif);
	
	private native int DmgrGetLastError();
	
	private native boolean DmgrGetDvc(int idvc, DVC dvc);
	
	private native boolean DmgrEnumDevices(int[] pcdvc);
	
	private native boolean DmgrFreeDvcEnum();
	
	private native boolean DeppEnable(HIF hif);
	
	private native boolean DeppDisable(HIF hif);
	
	private native boolean DeppPutReg(HIF hif, byte address, byte data, boolean overlap);
	
	private native boolean DeppGetReg(HIF hif, byte address, byte[] data, boolean overlap);
	
	private native boolean DeppPutRegSet(HIF hif, byte[] addressDataPair, int numberOfPairs, boolean overlap);
	
	private native boolean DeppGetRegSet(HIF hif, byte[] address, byte[] data, int numberOfDataReads, boolean overlap);
	
	private native boolean DeppPutRegRepeat(HIF hif, byte address, byte[] data, int size, boolean overlap);
	
	private native boolean DeppGetRegRepeat(HIF hif, byte address, byte[] data, int n, boolean overlap);
	
	
	public static void main(String[] args){
		AdeptSDKJavaLoader.loadNative();
		AdeptSDKJava asj = new AdeptSDKJava();
		int[] numberOfDevices = new int[1];
		boolean result = asj.jDmgrEnumDevices(numberOfDevices);
		
		int num = numberOfDevices[0];
		
		System.out.println("result " + result);
		System.out.println("number of Connected devices " + num);
		DVC dvc = asj.createDVCHandle();
		for(int i = 0; i < num; i++){
			asj.jDmgrGetDvc(i, dvc);
			String s = dvc.getSzName();
			String s2 = dvc.getszConn();
			System.out.println("Name of device is " + s);
			System.out.println("Connection string " + s2);
		}
		dvc.dispose();
		asj.DmgrFreeDvcEnum();
	}
	
	public static void writeArray(AdeptSDKJava asj, HIF hif, byte[] data){
		for(int i = 0; i < data.length; i++){
			asj.DeppPutReg(hif, (byte)i, data[i], false);
		}
	}
	

	
	public class AdeptSDKJavaException extends Exception{
		
	}
	
	public class HIFDisposedException extends AdeptSDKJavaException{
		
	}
	
	public class DeppNotEnabledException extends AdeptSDKJavaException{
		
	}
	
	private static final AdeptSDKJava instance = new AdeptSDKJava();
	
	public static AdeptSDKJava getInstance(){
		return instance;
	}
	
	public class HIF{

		private long handlePointer;
		private boolean disposed = true;
		
		private boolean deppEnabled = false;
		
		private HIF(){
			handlePointer = allocateHIF();
			disposed = false;
		}
		
		public void dispose(){
			if(!disposed){
				deallocateHIF(handlePointer);
				disposed = true;
			}
		}
		
		
		@Override
		protected void finalize() throws Throwable {
			if(!disposed){
				deallocateHIF(handlePointer);
				disposed = true;
			}
			super.finalize();
		}
		
	}
	
	public class DVC{

		private long handlePointer;
		private boolean disposed;
		private boolean loaded;
		
		private DVC(){
			handlePointer = allocateDVC();
			disposed = false;
			loaded = false;
		}
		
		public void dispose(){
			if(!disposed){
				deallocateDVC(handlePointer);
				disposed = true;
			}
		}
		
		public String getSzName(){
			if(loaded){
				return getDVCszName(this);
			}
			return null;
		}
		
		public String getszConn(){
			if(loaded){
				return getDVCszConn(this);
			}
			return null;
		}
		
		
		@Override
		protected void finalize() throws Throwable {
			if(!disposed){
				deallocateDVC(handlePointer);
				disposed = true;
			}
			super.finalize();
		}
		
	}
	

}
